﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Forms;

namespace AutoUI
{
    [Designer(typeof(FlowBarProDesigner))]
    [ToolboxItem(true)]
    [DisplayName("测试无效")]
    [Description("这是一款高级流动条控件")]
    [DefaultProperty("FlowBars_")]
    public partial class 高级流动条_ : Control
    {
        #region Fields

        /// <summary>
        /// 绘制流动条的笔
        /// </summary>
        private Pen _FlowPen = new Pen(Color.Red, 10);

        /// <summary>
        /// 转化之后的点:初始化和size改变都会更新这个集合
        /// </summary>
        public List<List<PointF>> realpointss = new List<List<PointF>>();

        private Color _EndColor = Color.White;

        /// <summary>
        /// 是否统一流动条颜色
        /// </summary>
        private bool _FlowBarColorCommon = false;

        private Color _FlowFluidColor = Color.Red;
        private bool _FlowFluidColorCommon;

        /// <summary>
        /// 设计器赋值到这里
        /// </summary>
        private List<List<PointF>> _Ps = new List<List<PointF>>();

        private SmoothingMode _SmoothingMode = SmoothingMode.AntiAlias;
        private Color _StartColor = Color.Cyan;
        private Timer _timer;
        private int offset = 4;
        //偏移,通过这个完成流动条的流动效果

        #endregion Fields

        #region Constructors

        public 高级流动条_()
        {
            InitializeComponent();
            this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            this.SetStyle(ControlStyles.DoubleBuffer, true);
            this.SetStyle(ControlStyles.ResizeRedraw, true);
            this.SetStyle(ControlStyles.Selectable, true);
            this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
            this.SetStyle(ControlStyles.UserPaint, true);
            // FlowBars_ =
            this.Size = new System.Drawing.Size(500, 250);
            _timer = new Timer();
            _timer.Enabled = true;
            _timer.Tick += Timer_Tick;
            Init();
        }

        protected override void InitLayout()
        {
            base.InitLayout();
            Init();
        }

        //protected override void SetBoundsCore(int x, int y, int width, int height, BoundsSpecified specified)
        //{
        //    width = width < 20 ? 20 : width;
        //    height = height < 20 ? 20 : height;
        //    switch (Orientation)
        //    {
        //        case Orientation.Horizontal:
        //            if (width < 3 * height)
        //            {
        //                base.SetBoundsCore(x, y, 300, 50, specified);
        //                return;
        //            }
        //            break;

        //        case Orientation.Vertical:
        //            if (height < 3 * width)
        //            {
        //                //300 90  ...30,90
        //                base.SetBoundsCore(x, y, 50, 300, specified);
        //                return;
        //            }
        //            break;
        //    }
        //    base.SetBoundsCore(x, y, width, height, specified);
        //}

        #endregion Constructors

        #region Properties

        /// <summary>
        /// 是否激活流动效果
        /// </summary>
        [Category("3.参数设置"), Description("是否激活流动效果"), DefaultValue(true), DisplayName("是否激活")]
        public bool Activate
        {
            get { return _timer.Enabled; }
            set
            {
                if (_timer != null)
                {
                    _timer.Enabled = value;
                }
                Invalidate();
            }
        }

        /// <summary>
        /// 设计状态
        /// </summary>
        [Category("4.设计时属性"), Description("编辑状态"), DisplayName("编辑状态")]
        public EnumDesignStatus DesignStatus { get; set; }

        /// <summary>
        /// 渐变结束颜色
        /// </summary>
        [Category("1.颜色设置"), Description("渐变结束颜色"), DisplayName("渐变结束颜色")]
        public Color EndColor
        {
            get { return _EndColor; }
            set
            {
                _EndColor = value;
                this.Invalidate();
            }
        }

        /// <summary>
        /// 是否统一流动条颜色
        /// </summary>
        [Category("1.颜色设置"), Description("统一流动条颜色"), DisplayName("统一流动条颜色")]
        public bool FlowBarColorCommon
        {
            get { return _FlowBarColorCommon; }
            set
            {
                _FlowBarColorCommon = value;

                this.Invalidate();
            }
        }

        /// <summary>
        /// 流动条管理:有每一个流动条的点集合及颜色等
        /// </summary>
        [Category("0.流动条管理"), Description("流动条详细设置"), DisplayName("流动条详细设置")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        [Localizable(true)]
        [MergableProperty(false)]
        public List<FlowBar> FlowBars_ { get; set; } = new List<FlowBar>();

        private bool comFlowFluidHeight = false;

        [Category("0.流动条管理"), Description("统一流动条高度"), DisplayName("统一流动条高度")]
        public bool ComFlowFluidHeight
        {
            get { return comFlowFluidHeight; }
            set
            {
                comFlowFluidHeight = value;
                Invalidate();
            }
        }

        private float flowBarHeight = 30f;

        [Category("0.流动条管理"), Description("流动条高度"), DisplayName("流动条高度")]
        public float FlowBarHeight
        {
            get { return flowBarHeight; }
            set
            {
                flowBarHeight = value;
                Invalidate();
            }
        }

        /// <summary>
        /// 流动液体统一颜色
        /// </summary>
        [Category("1.颜色设置"), Description("流动液体统一颜色"), DisplayName("流动液体统一颜色")]
        public Color FlowFluidColor
        {
            get { return _FlowFluidColor; }
            set
            {
                _FlowFluidColor = value;
                this.Invalidate();
            }
        }

        /// <summary>
        /// 是否统一流动条颜色
        /// </summary>
        [Category("1.颜色设置"), Description("统一流动条液体颜色"), DisplayName("统一流动条液体颜色")]
        public bool FlowFluidColorCommon
        {
            get { return _FlowFluidColorCommon; }
            set
            {
                _FlowFluidColorCommon = value;

                this.Invalidate();
            }
        }

        [Category("4.设计时属性"), Description("正在编辑的流动条的索引"), DisplayName("正在编辑的流动条的索引")]
        public int Indexline { get; set; } = 0;

        [Category("4.设计时属性"), Description("正在编辑的流动条的点的索引"), DisplayName("正在编辑的流动条的点的索引")]
        public int Indexpoint { get; set; } = -1;

        /// <summary>
        /// 是否激活流动效果
        /// </summary>
        [Category("4.设计时属性"), Description("绘制效果,一定程度影响性能(反锯齿)"), DisplayName("绘制效果")]
        public SmoothingMode SmoothingMode
        {
            get { return _SmoothingMode; }
            set { _SmoothingMode = value; }
        }

        /// <summary>
        /// 流动速度
        /// </summary>
        [Category("3.参数设置"), Description("流动速度,所有流动条的最快速度,值设置越小,越消耗性能"), DefaultValue(100), DisplayName("流动速度")]
        public int Speed
        {
            get { return _timer.Interval; }
            set
            {
                _timer.Interval = value;
                Invalidate();
            }
        }

        /// <summary>
        /// 渐变开始颜色
        /// </summary>
        [Category("1.颜色设置"), Description("渐变开始颜色"), DisplayName("渐变开始颜色")]
        public Color StartColor
        {
            get { return _StartColor; }
            set
            {
                _StartColor = value;
                this.Invalidate();
            }
        }

        /// <summary>

        #endregion Properties

        #region Methods

        protected override void SetBoundsCore(int x, int y, int width, int height, BoundsSpecified specified)
        {
            if (width < 100) width = 100;

            if (height < 100) height = 100;

            base.SetBoundsCore(x, y, width, height, specified);
        }

        /// <summary>
        /// 初始化每一个流动条的_ColorBlend/_FlowPen
        /// </summary>
        public void Init()
        {
            foreach (var flowBar in FlowBars_)
            {
                flowBar.RealPoints = flowBar.Points.Select((x) => { return new PointF(x.X * Width, x.Y * Height); }).ToList();

                if (FlowBarColorCommon)//统一流动条颜色
                {
                    flowBar._ColorBlend = new ColorBlend() { Colors = new Color[] { StartColor, EndColor, StartColor }, Positions = new float[] { 0, 0.5f, 1 } };
                }
                else
                {
                    flowBar._ColorBlend = new ColorBlend() { Colors = new Color[] { flowBar.StartColor, flowBar.EndColor, flowBar.StartColor }, Positions = new float[] { 0, 0.5f, 1 } };
                }
                if (FlowFluidColorCommon)//统一流动液体颜色
                {
                    flowBar._FlowPen = new Pen(FlowFluidColor, flowBar.FlowFluidHeight) { DashOffset = flowBar._offset };
                }
                else
                {
                    flowBar._FlowPen = new Pen(flowBar.FlowFluidColor, flowBar.FlowFluidHeight) { DashOffset = flowBar._offset };
                }
                if (ComFlowFluidHeight)//统一流动条高度
                {
                    flowBar.FlowBarHeight = FlowBarHeight;
                }
                else
                {
                }
                flowBar._FlowPen.DashPattern = new float[] { flowBar.FolwLength / flowBar.FlowFluidHeight, flowBar.GapLength / flowBar.FlowFluidHeight };
            }
            if (FlowBars_.Count > 0)
            {
                GetDrawPath();
            }
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            System.Drawing.Point point = PointToClient(Control.MousePosition);
            base.OnPaint(e);
            if (DesignMode)
            {
                Init();
            }
            var g = e.Graphics;
            if (SmoothingMode != SmoothingMode.Invalid)
            {
                g.SmoothingMode = SmoothingMode;
            }

            foreach (FlowBar fbb in FlowBars_)
            {
                foreach (var fp in fbb.FillPathpaths)//绘制扇形
                {
                    g.FillPath(fp.PathBrush, fp.Path);
                }
                foreach (var fl in fbb.FillLinepaths)//绘制矩形
                {
                    g.FillPath(fl.PathBrush, fl.Path);
                }
                foreach (var dl in fbb.DrawLinepaths)//绘制流动液体
                {
                    try
                    {
                        g.DrawPath(fbb._FlowPen, dl.Path);
                    }
                    catch (Exception)
                    {
                    }
                }
            }
            if (DesignStatus == EnumDesignStatus.Designing)
            {
                if (FlowBars_.Count > 0 && FlowBars_.Count > Indexline && Indexline >= 0)
                {
                    var d = FlowBars_[Indexline];
                    if (d.RealPoints.Count == 1)
                    {
                        {
                            //第一条线段的角度
                            var realpoints1 = FlowBars_[Indexline].RealPoints;
                            float startAngel1 = (float)(Math.Atan2(realpoints1[0].Y - point.Y, point.X - realpoints1[0].X) * SysConst.hudue);
                            //起点圆
                            CircleF c01 = new CircleF(realpoints1[0], d.FlowBarHeight);
                            //终点圆
                            CircleF c0h1 = new CircleF(point, d.FlowBarHeight);
                            //起点
                            var p0u1 = c01.PointOnPath(startAngel1 + 90);
                            var p0d1 = c01.PointOnPath(startAngel1 - 90);
                            //终点
                            var p1u1 = c0h1.PointOnPath(startAngel1 + 90);
                            var p1d1 = c0h1.PointOnPath(startAngel1 - 90);
                            //第一条线段的向量
                            var v11 = new Vector(point.X - realpoints1[0].X, realpoints1[0].Y - point.Y);
                            GraphicsPath gp1 = new GraphicsPath();
                            GraphicsPath gpl1 = new GraphicsPath();
                            gpl1.AddLine(realpoints1[0], point);//添加第一条中线

                            gp1.AddLine(p0u1, p1u1);//添加第一个矩形
                            gp1.AddLine(p1d1, p0d1);

                            LinearGradientBrush lb1 = new LinearGradientBrush(p0u1, p0d1, Color.Red, Color.Red);
                            lb1.InterpolationColors = FlowBars_.Last()._ColorBlend;
                            g.FillPath(lb1, gp1);//绘制第一个矩形
                            g.DrawPath(_FlowPen, gpl1);// 绘制第一条线
                        }
                    }
                    else if (d.RealPoints.Count > 1)
                    {
                        // GetDrawPath();
                        if (d.LastLine.EndPoint.X == point.X && d.LastLine.EndPoint.Y == point.Y)
                        {
                        }
                        else
                        {
                            var xx = GetPieAndRec(d.LastLine, point, d.FlowBarHeight, d);
                            if (xx.Item1 != null && xx.Item2 != null && xx.Item3 != null && xx.Item4 != null && xx.Item5 != null)
                            {
                                try
                                {
                                    g.FillPath(xx.Item3.PathBrush, xx.Item3.Path);
                                    g.FillPath(xx.Item4.PathBrush, xx.Item4.Path);
                                    g.DrawPath(xx.Item1.Pen, xx.Item1.Path);
                                    g.DrawPath(xx.Item2.Pen, xx.Item2.Path);
                                }
                                catch (Exception ex)
                                {
                                    g.DrawString(ex.Message, Font, Brushes.Red, new PointF(0, 0));
                                }
                            }
                        }
                    }
                }
            }
        }

        protected override void OnSizeChanged(EventArgs e)
        {
            Init();
            base.OnSizeChanged(e);
        }

        /// <summary>
        /// 将比例路径点转化为实际路径
        /// </summary>
        private void GetDrawPath()
        {
            for (int i = 0; i < FlowBars_.Count; i++)
            {
                if (FlowBars_[i].RealPoints.Count > 1)//至少两个点才绘制
                {
                    FlowBars_[i].DrawLinepaths.Clear();
                    FlowBars_[i].FillLinepaths.Clear();
                    FlowBars_[i].FillPathpaths.Clear();

                    AutoLine line1 = new AutoLine(FlowBars_[i].RealPoints[0], FlowBars_[i].RealPoints[1]);

                    FlowBars_[i].LastLine = line1;

                    #region 绘制第一条线段

                    #region 解决抗锯齿导致的模糊

                    CircleF c1_temp = new CircleF(FlowBars_[i].RealPoints[1], offset);
                    var p1_offset = c1_temp.PointOnPath(line1.Angel);
                    CircleF c1_offset = new CircleF(p1_offset, FlowBars_[i].FlowBarHeight);
                    var p1u_offset = c1_offset.PointOnPath(line1.Angel + 90);
                    var p1d_offset = c1_offset.PointOnPath(line1.Angel - 90);

                    #endregion 解决抗锯齿导致的模糊

                    //起点圆
                    CircleF c_start = new CircleF(FlowBars_[i].RealPoints[0], FlowBars_[i].FlowBarHeight);
                    //起点
                    var p1u = c_start.PointOnPath(line1.Angel + 90);
                    var p1d = c_start.PointOnPath(line1.Angel - 90);
                    //第一条线段的向量
                    GraphicsPath first_gp_rec = new GraphicsPath();
                    GraphicsPath first_gp_line = new GraphicsPath();
                    first_gp_line.AddLine(FlowBars_[i].RealPoints[0], p1_offset);//添加第一条中线
                    first_gp_rec.AddLine(p1u, p1u_offset);//添加第一个矩形
                    first_gp_rec.AddLine(p1d_offset, p1d);
                    LinearGradientBrush first_lb = new LinearGradientBrush(p1u, p1d, Color.Red, Color.Red);
                    //tudo:这里可以直接new一个_ColorBlend
                    first_lb.InterpolationColors = FlowBars_[i]._ColorBlend;
                    //tudo:这里的pen也应该需要优化
                    FlowBars_[i].DrawLinepaths.Add(new DrawLinepath() { Path = first_gp_line });
                    FlowBars_[i].FillLinepaths.Add(new FillLinepath() { Path = first_gp_rec, PathBrush = first_lb });

                    #endregion 绘制第一条线段

                    #region 如果大于两个点就绘制剩余的

                    for (int j = 2; j < FlowBars_[i].RealPoints.Count; j++)
                    {
                        var xx = GetPieAndRec(FlowBars_[i].LastLine, FlowBars_[i].RealPoints[j], FlowBars_[i].FlowBarHeight, FlowBars_[i]);
                        if (xx.Item1 != null && xx.Item2 != null && xx.Item3 != null && xx.Item4 != null)
                        {
                            FlowBars_[i].DrawLinepaths.Add(xx.Item1);
                            FlowBars_[i].DrawLinepaths.Add(xx.Item2);
                            FlowBars_[i].FillLinepaths.Add(xx.Item3);
                            FlowBars_[i].FillPathpaths.Add(xx.Item4);
                            FlowBars_[i].LastLine = xx.Item5;
                        }
                    }

                    #endregion 如果大于两个点就绘制剩余的
                }
            }
        }

        /// <summary>
        /// 获取路径
        /// </summary>
        /// <param name="line1">前一条线段</param>
        /// <param name="p">新点</param>
        /// <param name="FlowHeight">流动条高估</param>
        /// <param name="fb">流动条</param>
        /// <returns></returns>
        private FlowBarpath GetPieAndRec(AutoLine line1, PointF p, float FlowHeight, FlowBar fb)
        {
            AutoLine linetemp = new AutoLine(line1.EndPoint, p);
            //终点圆
            CircleF c_stop = new CircleF(line1.EndPoint, FlowHeight);
            var p2u = c_stop.PointOnPath(line1.Angel + 90);
            var p2d = c_stop.PointOnPath(line1.Angel - 90);
            var temp_angel = Vector.AngleBetween(line1.Vector, linetemp.Vector);

            if (temp_angel == 0 || temp_angel == 180)
            {
                return new FlowBarpath();
            }
            //求切点
            var QieDian = Common.GetQieDian(temp_angel > 0 ? p2u : p2d, p, FlowHeight);
            if (QieDian == null)
            {
                return new FlowBarpath();
            }
            //真实展示的角度
            AutoLine line2 = new AutoLine(QieDian[temp_angel > 0 ? 1 : 0], p);
            //正表示在左边 负表示在右边
            //扇形划过的角度
            var pie_angel = (float)Vector.AngleBetween(line2.Vector, line1.Vector);
            // Console.WriteLine("归一化后::" + pie_ange2.ToString());

            #region 解决抗锯齿导致的模糊

            CircleF c_temp1 = new CircleF(QieDian[temp_angel > 0 ? 1 : 0], offset);
            CircleF c_temp2 = new CircleF(p, offset);

            var p1_offset1 = c_temp1.PointOnPath(line2.Angel + 180);
            var p1_offset2 = c_temp2.PointOnPath(line2.Angel);
            CircleF c_offset1 = new CircleF(p1_offset1, FlowHeight);
            CircleF c_offset2 = new CircleF(p1_offset2, FlowHeight);

            var p1u_offset1 = c_offset1.PointOnPath(line2.Angel + 90);
            var p1d_offset2 = c_offset1.PointOnPath(line2.Angel - 90);
            var p1u_offset3 = c_offset2.PointOnPath(line2.Angel + 90);
            var p1d_offset4 = c_offset2.PointOnPath(line2.Angel - 90);

            #endregion 解决抗锯齿导致的模糊

            #region 绘制矩形

            CircleF c1 = new CircleF(QieDian[temp_angel > 0 ? 1 : 0], FlowHeight);
            GraphicsPath rec_gp = new GraphicsPath();
            GraphicsPath line_gp = new GraphicsPath();
            var p1hu = c1.PointOnPath(line2.Angel + 90);
            var p1hd = c1.PointOnPath(line2.Angel - 90);
            rec_gp.AddLine(p1u_offset1, p1u_offset3);
            rec_gp.AddLine(p1d_offset4, p1d_offset2);
            line_gp.AddLine(QieDian[temp_angel > 0 ? 1 : 0], p);//
            LinearGradientBrush lb = new LinearGradientBrush(p1hu, p1hd, Color.Red, Color.Red);
            lb.InterpolationColors = fb._ColorBlend;

            #endregion 绘制矩形

            #region 绘制扇形

            GraphicsPath path_gp = new GraphicsPath();
            GraphicsPath path_line = new GraphicsPath();
            path_gp.AddPie(new CircleF(temp_angel > 0 ? p2u : p2d, FlowHeight * 2), pie_angel > 0 ? -(line1.Angel + 90) : -(line1.Angel - 90), pie_angel > 0 ? pie_angel : pie_angel);

            PathGradientBrush pb = new PathGradientBrush(path_gp);
            pb.InterpolationColors = fb._ColorBlend;
            pb.CenterPoint = temp_angel > 0 ? p2u : p2d;
            try
            {
                path_line.AddArc(new CircleF(temp_angel > 0 ? p2u : p2d, FlowHeight), pie_angel > 0 ? -(line1.Angel + 90) : -line1.Angel + 90, pie_angel > 0 ? pie_angel : pie_angel);
            }
            catch (Exception)
            {
                return new FlowBarpath();
            }
            return new FlowBarpath()
            {
                Item1 = new DrawLinepath() { Path = line_gp },
                Item2 = new DrawLinepath() { Path = path_line },
                Item3 = new FillLinepath() { Path = rec_gp, PathBrush = lb },
                Item4 = new FillPathpath() { Path = path_gp, PathBrush = pb },
                Item5 = line2
            };

            // return (   line2);

            #endregion 绘制扇形
        }

        private void Timer_Tick(object sender, EventArgs e)
        {
            Invalidate();
            foreach (var flowBar in FlowBars_)
            {
                //   flowBar.time += _timer.Interval;
                // if (flowBar.time > flowBar.Speed)
                // {
                //  flowBar.time = 0;
                switch (flowBar.Active)
                {
                    case EnumRotateDirection.Stop:

                        break;

                    case EnumRotateDirection.Forward:
                        flowBar._offset++;
                        flowBar._FlowPen.DashOffset = flowBar._offset;
                        break;

                    case EnumRotateDirection.Reversal:
                        flowBar._offset--;
                        flowBar._FlowPen.DashOffset = flowBar._offset;

                        break;
                }
                // }
            }
        }

        #endregion Methods
    }
}